#include "lexer.h"
#include "lexerpackage.h"
#include "lexercomment.h"

#include "../typedef/token.h"
#include "symboltable.h"

#include <assert.h>
#include <stdio.h>

char *LexerPackage(char *ch, int *line, int *len, Lexer *plex, int size)
{
	assert(ch);
	assert(line);
	assert(len);
	assert(plex);
	int state;
	state = 17;
	Token *ptoken;
	ptoken = 0;
	while ((*len) < size) {
		switch (state)
		{
			case 17: {
				switch (*ch)
				{
					case '\n':
						(*line)++;
					case ' ':
					case '\t': {
						(*len)++;
						ch++;
						//解析package的其他东西
						state = 20;
						continue;
					}
					default: {
						printf("任何一个文件的开始,必须以package定义开头.\n");
						return 0;
					}

				}
				printf("错误的lexer package状态机.状态:17\n");
				return 0;
			}
				//package pkg_name.pkg_name ;
			case 20: {
				switch (*ch)
				{
					//注释需要跳过
					case '/': {
						ch = LexerComment(ch, line, len, plex, size, 0);
						if (ch == 0) {
							//表示不是注释
							printf("包名字只能含有a-z A-Z _ 请检查包的名字.\n");
							return 0;
						}
						(*len)++;
						ch++;
						continue;
					}
						//空格回车需要跳过
					case '\n':
						(*line)++;
					case ' ':
					case '\t': {
						(*len)++;
						ch++;
						continue;
					}
					default: {
						//字符串名字
						if (((*ch) >= 'a' && (*ch) <= 'z')
								|| ((*ch) >= 'A' && (*ch) <= 'Z')
								|| (*ch) == '_'
								|| ((*ch) >= '0' && (*ch) <= '9')) {
							state = 21;
							if (ptoken != 0) {
								printf("lexer package错误.token已经存在.\n");
								return 0;
							}
							ptoken = TokenInit(TokenType_Variable);
							ptoken->str = ch;
							ptoken->len++;
							ptoken->line = *line;
							(*len)++;
							ch++;
							continue;
						}
						printf("包名字只能含有a-z A-Z _ 请检查包的名字.%d\n", *ch);
						return 0;
					}

				}
				printf("错误的lexer package状态机.状态:20\n");
				return 0;
			}
			case 21: {
				switch (*ch)
				{
					case '.': {
						//表示读取子包
						state = 22;
						(*len)++;
						ch++;
						ptoken->name = SymbolTablePush(ptoken->str,
								ptoken->len);
						LexerPush(plex, ptoken);
						ptoken = TokenInit(TokenType_Get);
						LexerPush(plex, ptoken);
						ptoken = 0;
						continue;
					}
					case '\n': {
						(*line)++;
					}
					case ' ':
					case '\t': {
						//表示一个包读完
						ptoken->name = SymbolTablePush(ptoken->str,
								ptoken->len);
						LexerPush(plex, ptoken);
						ptoken = 0;
						return ch;
					}
					case ';': {
						(*len)++;
						ch++;
						ptoken->name = SymbolTablePush(ptoken->str,
								ptoken->len);
						LexerPush(plex, ptoken);
						ptoken = TokenInit(TokenType_End);
						LexerPush(plex, ptoken);
						ptoken = 0;
						return ch;
					}
					case '/': {
						//表示一个包读完,后面跟随着一个注释
						ptoken->name = SymbolTablePush(ptoken->str,
								ptoken->len);
						LexerPush(plex, ptoken);
						ptoken = 0;
						(*len)++;
						ch++;
						ch = LexerComment(ch, line, len, plex, size, 0);
						if (ch == 0) {
							//表示不是注释
							printf("包名字只能含有a-z A-Z _ 0-9请检查包的名字.%d\n", *ch);
							return 0;
						}
						return ch;
					}
					default: {
						if (((*ch) >= 'a' && (*ch) <= 'z')
								|| ((*ch) >= 'A' && (*ch) <= 'Z')
								|| (*ch) == '_'
								|| ((*ch) >= '0' && (*ch) <= '9')) {
							(*len)++;
							ch++;
							ptoken->len++;
							continue;
						}
						printf("包名字只能含有a-z A-Z _ 0-9请检查包的名字.%d\n", *ch);
						return 0;
					}
				}
				printf("错误的lexer package状态机.状态:21\n");
				return 0;
			}
			case 22: {
				//子包
				if (((*ch) >= 'a' && (*ch) <= 'z')
						|| ((*ch) >= 'A' && (*ch) <= 'Z') || (*ch) == '_'
						|| ((*ch) >= '0' && (*ch) <= '9')) {
					state = 21;
					ptoken = TokenInit(TokenType_Variable);
					ptoken->str = ch;
					ptoken->len++;
					ptoken->line = *line;
					(*len)++;
					ch++;
					continue;
				}
				printf("包名字只能含有a-z A-Z _ 0-9 请检查包的名字.%d\n", *ch);
				return 0;
			}
		}
	}
	return ch;
}
